package com.itshare.video.service.impl;

import cn.hutool.crypto.SecureUtil;
import com.itshare.video.common.core.constant.enums.ApiInfo;
import com.itshare.video.common.core.validator.UpdateGroup;
import com.itshare.video.common.dto.Result;
import com.itshare.video.common.dto.ViewObject;
import com.itshare.video.mapper.UserMapper;
import com.itshare.video.mapper.UserRoleMapper;
import com.itshare.video.mapper.custom.UserMapperCustom;
import com.itshare.video.pojo.dto.EmailLoginDTO;
import com.itshare.video.pojo.dto.RegisterDTO;
import com.itshare.video.pojo.dto.UserInfoDTO;
import com.itshare.video.pojo.dto.UserTokenDTO;
import com.itshare.video.pojo.po.Role;
import com.itshare.video.pojo.po.User;
import com.itshare.video.pojo.po.UserMessage;
import com.itshare.video.pojo.po.UserRole;
import com.itshare.video.service.UserService;
import com.itshare.video.util.AccountUtil;
import com.itshare.video.util.MessageUtil;
import com.itshare.video.util.mapping.UserBeanMapping;
import com.itshare.video.util.mq.UserMessageMq;
import lombok.extern.slf4j.Slf4j;
import org.mapstruct.factory.Mappers;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.Date;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @Author lyr
 * @create 2020/10/24 08:42
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapperCustom userMapperCustom;
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private UserMessageMq userMessageMq;


    /**
     * 映射器
     */
    UserBeanMapping userBeanMapping = Mappers.getMapper(UserBeanMapping.class);


    /**
     * 邮箱登录
     *
     * @param emailLoginDTO
     * @return
     */
    @Override
    public User login(EmailLoginDTO emailLoginDTO) {
        emailLoginDTO.setPassword(SecureUtil.sha1(emailLoginDTO.getPassword()));
        User user = userMapperCustom.selectUserByPrimaryKeys(null, emailLoginDTO.getEmail(), emailLoginDTO.getPassword());
        if (user == null) {
            return user;
        }
        Role role = userMapperCustom.selectRole(user.getUserId().intValue());
        user.setRoleId(role.getRoleId());
        return user;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> register(@RequestBody @Validated RegisterDTO registerDTO) {
        //加密密码
        registerDTO.setPassword(SecureUtil.sha1(registerDTO.getPassword()));
        User user = new User()
                .withEmail(registerDTO.getEmail())
                .withPassword(registerDTO.getPassword());
        // .withRoleId(registerDTO.getRole());

        try {
            userMapper.insertSelective(user);
            // int row = userMapperCustom.insertOne(registerDTO);
        } catch (Exception ex) {
            log.error("异常 {}", ex.getMessage());
            return Result.ofCode(ApiInfo.BASIC_ERROR)
                    .setMessage("该账户以及注册了");
        }
        //插入用户角色权限
        UserRole userRole = new UserRole()
                .withRoleId(registerDTO.getRole())
                .withUserId(user.getUserId().intValue());
        userRoleMapper.insertSelective(userRole);
        log.info("数据库主键 {}", registerDTO.getPk());
        return Result.ofCode(ApiInfo.OK)
                .setMessage("注册成功");
    }


    /**
     * 更新用户个人信息
     *
     * @param userInfoDTO
     * @return
     */
    @Override
    public ViewObject updateUserInfo(@Validated(UpdateGroup.class) UserInfoDTO userInfoDTO, UserTokenDTO userTokenDTO) {
        //前端信息转换
        User user = userBeanMapping.fromUserDTO(userInfoDTO);
        user.withUserId(userTokenDTO.getId().longValue())
                .withUpdatedTime(new Date());
        try {
            log.info("user avatar {}", user.getAvatar());
            userMapper.updateByPrimaryKeySelective(user);
        } catch (Exception ex) {
            //信息更新失败
            log.error("信息更新失败 {}", ex.getMessage());
        }
        return ViewObject.ofCode(ApiInfo.OK)
                .put("userInfo", userInfoDTO);
    }

    /**
     * 获取用户信息
     *
     * @param userId 用户ID
     * @return
     */
    @Override
    public Result<UserInfoDTO> getUserInfo(Long userId) {
        User user = Optional.ofNullable(userMapper.selectByPrimaryKey(userId)).orElse(new User());

        UserInfoDTO userInfoDTO = userBeanMapping.fromUser(user);
        if (userInfoDTO.getAvatar() == null) {
            userInfoDTO.setAvatar("http://666.itshare.club/1603509156777");
        }
        log.info("user {}", userInfoDTO);
        return Result.<UserInfoDTO>ofCode(ApiInfo.OK)
                .setData(userInfoDTO);
    }


    /**
     * 冻结用户账号，不能发布视频
     *
     * @param userId
     * @return
     */
    @Override
    public Result<?> setUserAccountFreezeForUpload(Integer userId, Duration duration) {
        String accountSet = AccountUtil.getAccountFreezeSetName(userId);
        redisTemplate.opsForValue().set(accountSet,"1",duration);
        UserMessage userMessage = MessageUtil.setVideoDelete(userId);
        //不能发布视频
        userMessage.withToUserMessage("您被用户举报，视频有违规行为 ，已经冻结账户"+duration+"天"+"，期间不能发布视频");
        userMessageMq.sentMsg(userMessage);

        return Result.of(ApiInfo.OK);
    }




    @Override
    public boolean isUserAccountFreeze(Integer userId) {
        String accountSet = AccountUtil.getAccountFreezeSetName(userId);
        Object obj = redisTemplate.opsForValue().get(accountSet);
        //如果redis 存在用户数据，说明用户数据被冻结
        return obj!=null;
    }

    /**
     * 查询用户剩余冻结时间
     *
     * @param userId
     * @return
     */
    @Override
    public Long getTTLOfAccountFreeze(Integer userId) {
        String accountSet = AccountUtil.getAccountFreezeSetName(userId);
        return redisTemplate.getExpire(accountSet, TimeUnit.HOURS);

    }
}
